/**
 * 手写 PromiseAll
 * 
 */
function promiseAll(arr) {
    return new Promise((resolve, reject) => {
        if (!(arr instanceof Array)) {
            return reject(new Error('Invalid argument'));
        }
        let resultArr = new Array(arr.length);
        let count = 0;
        for (let i = 0; i < arr.length; i++) {
            Promise.resolve(arr[i]).then(res => {
                count++;
                resultArr[i] = res;
                if (count === arr.length) {
                    resolve(resultArr)
                }
            }).catch(reject);
        }

    })
}

const promiseGenerator = (num) =>
    new Array(num)
        .fill(0)
        .map((v, i) =>
            new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(i);
                }, Math.random() * 1000);
            })
        );
const proAll = promiseGenerator(4)
console.log('proAll:', proAll);


promiseAll(proAll).then(console.log)


// 2. 串行

const promiseFuncGenerator = (num) =>
    new Array(num)
        .fill(0)
        .map((v, i) => () =>
            new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log('index:', i);

                    resolve(i);
                }, Math.random() * 1000);
            })
        );
const promiseFunAll = promiseFuncGenerator(4)
const promiseChain = (promiseFunAll) => {
    promiseFunAll.reduce((total, item) => {
        return total.then(res => {
            return item()
        })
    }, Promise.resolve(-1))
}
promiseChain(promiseFunAll)


// 3. 设计一个调度器，每次只执行固定数目的Promise
const promiseScheduler = (promiseFunAll, limit) => {
    if (!Array.isArray(promiseFunAll)) throw new Error("Invalid Array")
    function run() {
        promiseFunAll.shift()().then(res => {
            promiseFunAll.length && run()
        })
    }
    for (let i = 0; i < limit; i++) {
        run()
    }
}

// lazyman
// 闭包特性
// delay 库
// promise.race
// 实现一个wrap去包裹promise，随时可以abort